﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using VRacer;
using System.Collections.ObjectModel;
using VRacer.Controls;
using VRacer.Connection;

namespace VRacer.Pages
{
    /// <summary>
    /// Interaction logic for Game.xaml
    /// </summary>
    public partial class GamePage : Page
    {
        public readonly static DependencyProperty GameProperty = DependencyProperty.Register("Game", typeof(Game), typeof(GamePage), new PropertyMetadata(new PropertyChangedCallback(GameChanged)));

        private ObservableCollection<Message> _messages = new ObservableCollection<Message>();


        public GamePage()
        {
            this.SetBinding(GameProperty, new Binding("Game") { Source = Business.Instance });            

            this.Unloaded += new RoutedEventHandler(Game_Unloaded);
        }

        private static void GameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Game oldGame = (Game)e.OldValue;
            Game newGame = (Game)e.NewValue;
            (d as GamePage).GameChanged(oldGame, newGame);
        }

        private void GameChanged(Game oldGame, Game newGame)
        {
            Dispatcher.BeginInvoke((DefaultDelegate)(() =>
            {
                //unbind from old game
                if (oldGame != null)
                {
                    if (oldGame is RemoteGame)
                    {
                        var remoteGame = (RemoteGame)oldGame;
                        remoteGame.Connection.Error -= Connection_Error;
                    }
                    oldGame.Message -= Game_Message;

                    oldGame.End();
                }

                //bind to new game
                if (newGame != null)
                {
                    newGame.Message += Game_Message;

                    if (newGame is RemoteGame)
                    {
                        var remoteGame = (RemoteGame)newGame;
                        remoteGame.Connection.Error += Connection_Error;
                    }

                    if (newGame.State == GameState.Uninitialized)
                        newGame.Initialize();
                }

                this.DataContext = newGame;
            }));
        }

        void Connection_Disconnected(object sender, EventArgs e)
        {
            throw new NotImplementedException();
        }

        void Connection_Error(object sender, ErrorEventArgs e)
        {
            Dispatcher.BeginInvoke((DefaultDelegate)(() =>
            {
                Business.Show(e.Exception);
                Business.Instance.Page = Urls.MainMenu;
            }));
        }

        void Game_Message(object sender, VRacer.MessageEventArgs e)
        {
            Dispatcher.Invoke((DefaultDelegate)(() =>
            {
                Messages.Clear();
                Messages.Add(e.Message);
            }));
        }

        void Game_Unloaded(object sender, RoutedEventArgs e)
        {
            BindingOperations.ClearAllBindings(this);
            Business.Instance.Game.End();
        }

        private void Border_MouseDown(object sender, MouseButtonEventArgs e)
        {
            Business.Instance.Game.Start();
        }

        public Game Game
        {
            get { return (Game)GetValue(GameProperty); }
            set { SetValue(GameProperty, value); }
        }

        public ObservableCollection<Message> Messages
        {
            get { return _messages; }
            set { _messages = value; }
        }

        private void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            var source = sender as TextBox;
            if (source != null && Game is RemoteGame)
            {
                if (e.Key == Key.Enter && source.Text.Length > 0)
                {
                    (Game as RemoteGame).SendMessage(source.Text);
                    source.Text = "";
                e.Handled = true;
                }

            }
        }
    }
}
